#include <linux/cpumask.h>

static struct cpumask __cpu_present_mask = {};
static struct cpumask __cpu_possible_mask = {};
static struct cpumask __cpu_online_mask = {};
static struct cpumask __cpu_active_mask = {};

/*
 * cpu_bit_bitmap[] is a special, "compressed" data structure that
 * represents all NR_CPUS bits binary values of 1<<nr.
 *
 * It is used by cpumask_of() to get a constant address to a CPU
 * mask value that has a single bit set only.
 */

/* cpu_bit_bitmap[0] is empty - so we can back into it */
#define MASK_DECLARE_1(x) [x + 1][0] = (1UL << (x))
#define MASK_DECLARE_2(x) MASK_DECLARE_1(x), MASK_DECLARE_1(x + 1)
#define MASK_DECLARE_4(x) MASK_DECLARE_2(x), MASK_DECLARE_2(x + 2)
#define MASK_DECLARE_8(x) MASK_DECLARE_4(x), MASK_DECLARE_4(x + 4)

const unsigned long cpu_bit_bitmap[BITS_PER_LONG + 1][BITS_TO_LONGS(NR_CPUS)] = {

    MASK_DECLARE_8(0),
    MASK_DECLARE_8(8),
    MASK_DECLARE_8(16),
    MASK_DECLARE_8(24),
#if BITS_PER_LONG > 32
    MASK_DECLARE_8(32),
    MASK_DECLARE_8(40),
    MASK_DECLARE_8(48),
    MASK_DECLARE_8(56),
#endif
};

const struct cpumask *cpumask_of(unsigned int cpu)
{
    const unsigned long *p = cpu_bit_bitmap[1 + cpu % BITS_PER_LONG];

    p -= cpu / BITS_PER_LONG;

    return to_cpumask(p);
}

struct cpumask *cpu_present_mask(void)
{
    return &__cpu_present_mask;
}

struct cpumask *cpu_possible_mask(void)
{
    return &__cpu_possible_mask;
}

struct cpumask *cpu_online_mask(void)
{
    return &__cpu_online_mask;
}

void set_cpu_possible(unsigned int cpu, bool possible)
{
    assign_bit(cpu, cpumask_bits(&__cpu_possible_mask), (possible));
}

void set_cpu_present(unsigned int cpu, bool possible)
{
    assign_bit(cpu, cpumask_bits(&__cpu_present_mask), (possible));
}

void set_cpu_online(unsigned int cpu, bool possible)
{
    assign_bit(cpu, cpumask_bits(&__cpu_online_mask), (possible));
}

#if NR_CPUS > 1
bool cpu_online(unsigned int cpu)
{
    return cpumask_test_cpu(cpu, &__cpu_online_mask);
}

bool cpu_active(unsigned int cpu)
{
    return cpumask_test_cpu(cpu, &__cpu_active_mask);
}

void set_cpu_active(unsigned int cpu, bool active)
{
    assign_bit(cpu, cpumask_bits(&__cpu_active_mask), (active));
}

bool cpu_dying(unsigned int cpu)
{
    return false; //todo
}
#endif
